/*******************************************************************************
********************************************************************************
** COPYRIGHT:      (c) 1995-2005 Rohde & Schwarz, Munich
** MODULE:         TCPexample.c
** ABBREVIATION:   
** LANGUAGE:       C
** ABSTRACT:       Example for Receiver Host Control. 
** PREMISES:       
** REMARKS:        
** REVIEW:         
*******************************************************************************/

/* INCLUDE FILES **************************************************************/

#define LINUX 1

#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>

typedef int SOCKET;

#include <stdio.h>
#include <string.h>
#include <cpgplot.h>

/* LOCAL DEFINES **************************************************************/

#define BYTEORDER_SWAPPED   0
#define TRACE_ASCII         0

/* Definitions for Receiver Remotecontrol Port */

#define IP_Receiver           "130.155.178.69"	/*default Receiver ip address */
#define PORT_Receiver          5555		    /* default Receiver port number */

/* LOCAL TYPES DECLARATION ****************************************************/
typedef enum
{ 
    false,
    true
} bool;

typedef struct __spectralpoint {
  unsigned long int  frequency;
  unsigned long int  levelsum;
  unsigned long int  nlevels;
} _spectralpoint ;

/* LOCAL VARIABLES DEFINITION **************************************************/
static bool bShowHelp = false;
_spectralpoint *spectralpoints;
int n_spectralpoints;

bool cloop;
unsigned long int tbuf[100000];

void make_plot(void);

/* FUNCTION *******************************************************************/
unsigned int MySend(int sd, char *pBuffer)

/*
SPECIFICATION:
Send string to Receiver. String must be terminated with 0 (valid C string).

PARAMETERS:
int sd :        valid socket descriptor
char *pBuffer : Pointer to string

PRECONDITIONS: 
SIDE_EFFECTS: 

RETURN_VALUES: 
number of characters sent

EXCEPTIONS: 
*******************************************************************************/
{
  unsigned int nLen;
  nLen = send(sd, pBuffer, strlen(pBuffer), 0);
  if (nLen != strlen(pBuffer))
    {
      printf("Error writing to Receiver.\n");
      cloop = false;
    }
  return nLen;
}

char *memstr(char *pBuffer, int nLen, char *pStr)
{
  char *pTempStr = pStr;
  int Strlen = strlen(pStr);
  while (nLen && Strlen)
    {
      if (*pBuffer == *pTempStr)
        {
	  pTempStr++;
	  Strlen--;
        }
      else
        {
	  pTempStr = pStr;
	  Strlen = strlen(pStr);
        }
      nLen--;
      pBuffer++;
    }
  if (!Strlen)
    {
      return pBuffer-strlen(pStr);
    }
  else
    {
      return NULL;
    }
}

/* FUNCTION *******************************************************************/
int CheckForBinary(char *pBuffer, int nLen)

/*
SPECIFICATION:
PARAMETERS:
char *pBuffer : 
int nLen : 
PRECONDITIONS: 
SIDE_EFFECTS: 
RETURN_VALUES: 
EXCEPTIONS: 
*******************************************************************************/
{
  char *pTempTempBuffer = pBuffer;
  int nTempLen = nLen;
  static char *pBinary;
  static int nCount = 0;
  bool bLeave = false;
  
  static int internalState = 0;
  static int nCountCount = 0;
  
  while (!bLeave)
    {
      switch(internalState)
        {
        case 0:
	  pBinary = strchr(pTempTempBuffer, '#');
	  if (pBinary != NULL)
            {
	      internalState = 2;
	      pBinary++;
	      nTempLen -= (pBinary - pTempTempBuffer);
	      if (!nTempLen)
                {
		  bLeave = true;
		  internalState = 1;
                }
            }
	  else
            {
	      bLeave = true;
            }
	  break;
        case 1:
	  // # was last byte in previous string
	  pBinary = pTempTempBuffer;
	  internalState = 2;
	  break;
        case 2:
	  // #x x=1..9 ?
	  if ((*pBinary >= '1') && (*pBinary <= '9'))
            {
	      // Binarydata 
	      nCountCount = *pBinary - '0';
	      nCount = 0;
	      internalState = 4;
	      pBinary++;
	      nTempLen--;
	      if (!nTempLen)
                {
		  bLeave = true;
		  internalState = 3;
                }
            }
	  else
            {
	      // no binarydata
	      internalState = 0;
	      nTempLen -= pBinary - pTempTempBuffer;
	      pTempTempBuffer = pBinary;
            }
	  break;
        case 3:
	  // #x x was last byte in previous string
	  pBinary = pTempTempBuffer;
	  internalState = 4;
	  break;
        case 4:
	  // #xabc -> parsing abc
	  while (nCountCount && nTempLen)
            {
	      nCount = 10 * nCount + *pBinary - '0';
	      nCountCount--;
	      nTempLen--;
	      pBinary++;
            }
	  if (nCountCount)
            {
	      // Stringlength was not sufficient
	      internalState = 3;
	      bLeave = true;
            }
	  else
            {
	      internalState = 5;
            }
	  break;
        case 5:
	  // Binarystring skipped
	  if (nTempLen > nCount)
            {
	      nTempLen -= nCount;
	      pBinary += nCount;
	      pTempTempBuffer = pBinary;
	      internalState = 0;
            }
	  else
            {
	      internalState = 6;
	      nCount -= nTempLen;
	      bLeave = true;
            }
	  break;
        case 6:
	  // Binarystring was longer as previous string
	  pBinary = pTempTempBuffer;
	  internalState = 5;
	  break;
        }
    }
  return internalState;
}

/* FUNCTION *******************************************************************/
bool ReadString(int sd, char *pBuffer, int nMaxLen, bool bWait)

/*
SPECIFICATION:
Reading a string from Receiver. At return, string will be a valid C string
terminated with zero.
&SRQ\r\n will be recognized and deleted from the rest of the string. 
Reading will be done until linefeed is encountered as the last character
received from Receiver.

PARAMETERS:
int sd :        valid socket descriptor
char *pBuffer : Pointer to buffer
int nMaxLen :   Maximum number of characters to be read
bool bWait :    true -> read until last character is linefeed
                false -> don't wait for linefeed as last character
PRECONDITIONS: 
SIDE_EFFECTS: 

RETURN_VALUES: 
false -> Encountered SRQ message in string
true -> no SRQ message from Receiver

EXCEPTIONS: 
*******************************************************************************/
{
  char* pTempBuffer;
  int nTempMaxLen;
  int nBinaryState;
  int nLen;
  int nTempLen;
  char *pSRQ;
  int e;
  bool bSrq = false;
  int nTotalLen = 0;
  do
    {
      pTempBuffer = pBuffer;
      nTotalLen = 0;
      nTempMaxLen = nMaxLen;
      nBinaryState = 0;
      
      // Wait til LF is last character in received string
      while (nTempMaxLen)
        {
	  nLen = recv(sd, pTempBuffer, nTempMaxLen, 0);
	  pTempBuffer[nLen] = 0;
	  nTempLen = nLen;
	  
	  // searching '#' (Binarystring)
	  nBinaryState = CheckForBinary(pTempBuffer, nLen);
	  
	  //printf("Received String = <%s>", pTempBuffer);
          
	  if (nLen >= 0)
            {
	      nTempMaxLen -= nLen;
	      pTempBuffer += nLen;
	      nTotalLen += nLen;
            }
	  if (nLen == 0)
            {
	      printf("Socket was closed.\n");
	      exit(1);
            }
	  if (nLen < 0)
            {
	      printf("error on reading socket.\n");
	      
	      make_plot();
            }
	  if ((pBuffer[nTotalLen-1] == '\n') && (nBinaryState == 0))
            {
	      pBuffer[nTotalLen] = 0;
	      break;
            }
        }
      if (!nTempMaxLen)
        {
	  printf("error: nTempMaxLen was too short.\n");
	  exit(1);
        }
      // Look for SRQ message
      do
        {
	  pSRQ = memstr(pBuffer, nTotalLen, "&SRQ\r\n");
	  if (pSRQ != NULL)
            {
	      // SRQ message encountered
	      bSrq = true;
	      // delete SRQ message from received string            
	      memmove(pSRQ, pSRQ+6, nTotalLen-(pBuffer-pSRQ)-5);
	      nTotalLen -= 6;
            }
	  else
            {
            }
        } while (pSRQ != NULL);
    } while (!nTotalLen && bWait);    
  return bSrq;
}

/* FUNCTION *******************************************************************/
bool ReadTraces(int sd)

/*
SPECIFICATION:
Read Status:Trace register, MTRACE and ITRACE.

PARAMETERS:
int sd :    valid socket descriptor

PRECONDITIONS: 
SIDE_EFFECTS: 
RETURN_VALUES: 
false -> Encountered SRQ message in string
true -> no SRQ message from Receiver

EXCEPTIONS: 
*******************************************************************************/
{
  static char cBuffer[120000];
  char *pMtrace;
  bool bSrq = false;
  int stat_trace;
#if (TRACE_ASCII)
  char *pItrace;
  int nCount1;
  int nCount2;
#endif
  int i;
  char* pBuffer;
  int nLenLen;
  int nLen;
  int nMTraceLen;
  unsigned long int nLevel;
  int nKanal;
  unsigned int nFreq;
  int startn = n_spectralpoints;
  
  /* Clear limit exceeded event and read all trace information */
  MySend(sd, "STAT:TRAC?;:TRAC? MTRACE;TRAC? ITRACE\n");
  bSrq |= ReadString(sd, cBuffer, sizeof(cBuffer) -1, true);
  
  /* Search for first ;
     this is the delimitor between STAT:TRAC? and TRAC? MTRACE answer */
  pMtrace = strstr(cBuffer, ";");
  if (pMtrace != NULL)
    {
      *pMtrace = '\0';
      pMtrace++;
    }
  else
    {
      printf("error reading traces. no ; found.\n");
      exit(1);
    }
  /* Convert STAT:TRACE contents to binary */
  stat_trace = atoi(cBuffer);
#if (TRACE_ASCII)
  /* Search for next ;
     this is the delimitor between TRAC? MTRACE and TRAC? ITRACE answer */
  pItrace = strstr(pMtrace, ";");
  if (pItrace != NULL)
    {
      *pItrace = '\0';
      pItrace++;
      printf("MTRACE: %s\n", pMtrace);
      printf("ITRACE: %s", pItrace);
      /*
       *  Check, if amount of data equal in those two traces.
       */
      nCount1 = 0;
      nCount2 = 0;
      for (i=0; i<strlen(pMtrace); i++) {
	if (pMtrace[i] == ',') {
	  nCount1++;
	}
      }
      for (i=0; i<strlen(pItrace); i++) {
	if (pItrace[i] == ',') {
	  nCount2++;
	}
      }
      nCount2 /= 2;
      if (nCount1 != nCount2) {
	printf("Error: element-count not equal in  "
	       "MTRACE <%d> and ITRACE <%d> !!!!\n", nCount1, nCount2);
	exit(1);
      }
      printf("element count = %d\n", nCount1);
    }
  else
    {
      printf("error reading traces. no ; found\n");
      exit(1);
    }
#else 
  /* Traces will be transferred as binary data
   * They have to be converted into ascii now.
   */
  
  pBuffer = pMtrace;
  nLenLen = pBuffer[1] - '0';
  nLen = 0;
  for (i=0; i<nLenLen; i++)
    {
      nLen = nLen * 10 + pBuffer[2+i] - '0';
    }
  if (nLen == 1)
    {
      printf("MTRACE is empty !\n");
      pBuffer += 2+i+2;
    }
  else if (nLen % 2)
    {
      printf("error in MTRACE Length: <%d>\n", nLen);
      exit(1);
    }
  else
    {
      nLen /= 2;
      nMTraceLen = nLen;
      pBuffer += 2+nLenLen;
      for (i=0; i<nLen; i++)
        {
	  nLevel = *((short *)(pBuffer+i*2));
#if (!BYTEORDER_SWAPPED)
	  nLevel = ntohs((short)nLevel);
#endif
	  if (nLevel == 2000) {
	    /* Wraparound mark
	     * WrapAround();
	     */
	  }
	  /* spectralpoints = realloc(spectralpoints, (++n_spectralpoints) * sizeof(_spectralpoint)); */
	  /* spectralpoints[nKanal].level = nLevel % 65384; */
	  tbuf[i] = nLevel;
	  /* if (i < (nLen-1)) { */
	  /*   printf("%d,%+hd,", nKanal,nLevel); */
	  /* } */
	  /* else { */
	  /*   printf("%d,%+hd\n", nKanal,nLevel); */
	  /* } */
        }
      if (pBuffer[i*2] != ';') {
	printf("error: ; between MTRACE and ITRACE is not correct!\n");
	exit(1);
      }
      pBuffer += i*2+1;
    }
  /* Output ITRACE */
  nLenLen = pBuffer[1] - '0';
  nLen = 0;
  for (i=0; i<nLenLen; i++)
    {
      nLen = nLen * 10 + pBuffer[2+i] - '0';
    }
  if (nLen == 1)
    {
      printf("ITRACE is empty !\n");
    }
  else if (nLen % 6)
    {
      printf("error in ITRACE Length: <%d>\n", nLen);
      exit(1);
    }
  else
    {
      nLen /= 6;
      pBuffer += 2+nLenLen;
      for (i=0; i<nLen; i++)
        {
	  nKanal = *((short *)(pBuffer+i*6));
	  nFreq = *((unsigned long *)(pBuffer+i*6+2));
#if (!BYTEORDER_SWAPPED)
	  nKanal = ntohs((short)nKanal);
	  nFreq = ntohl(nFreq);
#endif
	  spectralpoints[nKanal].frequency = nFreq;
	  spectralpoints[nKanal].levelsum += tbuf[i];
	  spectralpoints[nKanal].nlevels++;
	  n_spectralpoints = (nKanal > n_spectralpoints) ? nKanal : n_spectralpoints;
	  /* if (i < (nLen-1)) { */
	  /*   printf("%d,%ld,", nKanal, nFreq); */
	  /* } */
	  /* else { */
	  /*   printf("%d,%ld\n", nKanal, nFreq); */
	  /* } */
        }
      if (pBuffer[i*6] != '\r')
        {
	  printf("error: CR after ITRACE is not correct!\n");
	  exit(1);
        }
      if (nLen != nMTraceLen)
        {
	  printf("Length of MTRACE <%d> and ITRACE <%d> not equal !\n", 
		 nMTraceLen, nLen);
	  exit(1);
        }
    }
#endif
  if (stat_trace & 0x24)
    {
      printf("trace overrun occured !!!!!!! stat_trace = 0x%X\n", stat_trace);
    }
  return bSrq;
}


/* FUNCTION *******************************************************************/
main(int argc, char **argv)

/*
SPECIFICATION:
Opens a connection to Receiver. Performs some initialisations and starts a
frequency scan between 118 MHz and 136 MHz with 25 kHz steps. Reads all 
results until scan stops. 

PARAMETERS:
nothing

PRECONDITIONS: 
SIDE_EFFECTS: 
RETURN_VALUES: 
EXCEPTIONS: 
*******************************************************************************/
{
  struct sockaddr_in  addr;
  int err, i;
  char cBuffer[200];
  char setbuf[80];
  unsigned int FreqStart;
  unsigned int FreqStop;
  int FreqStep;
  int BandWidth;
  bool bSrq;
  SOCKET m_nSocketID;
  cloop = true;
  
  unsigned long int naspectralpoints;
  float resolutionmhz = 1.0, bandwidthmhz = 2000;
  naspectralpoints = (unsigned long int)(bandwidthmhz / resolutionmhz) * 2;
  
  spectralpoints = malloc(naspectralpoints * sizeof(_spectralpoint));
  for (i = 0; i < naspectralpoints; i++) {
    spectralpoints[i].levelsum = 0;
    spectralpoints[i].nlevels = 0;
  }
  n_spectralpoints = 0;
  
  if ((argc != 1) && (argc != 2) && (argc != 3))
    {
      bShowHelp = true;
    }
  else
    {
      if ((argc == 2) && ((!strcmp(argv[1], "-?")) || (!strcmp(argv[1], "-h"))))
	{
	  bShowHelp = true;
	}
    }
  
  if (bShowHelp == true)
    {
      printf("\nUsage: %s [IP-Address] [Portnumber]\n", argv[0]);
      printf("       Default IP-Address is 89.10.11.23\n");
      printf("       Default Portnumber is 5555\n");
      
      return 0;
    }
  
  /* create a new socket descriptor */
  m_nSocketID = socket(AF_INET, SOCK_STREAM, 0);
  if (m_nSocketID == -1)
    {
      printf("Could not create socket\n");
    }
  else
    {
      /* we have got a valid socket descriptor. 
	 now setup a connection request to Receiver */
      memset(&addr, 0, sizeof(addr));
      addr.sin_family      = AF_INET;
      /* fill out IP-Address with above defined values */
      addr.sin_addr.s_addr = inet_addr(IP_Receiver);
      
      
      if (argc >= 2)
	{
	  addr.sin_addr.s_addr = inet_addr(argv[1]);
	}
      if (argc >= 3)
	{
	  addr.sin_port        = htons((short)atoi(argv[2]));
	}
      else
	{
	  addr.sin_port        = htons(PORT_Receiver);
	}
      
      
      /* now do the connection */
      err = connect(m_nSocketID, (struct sockaddr *)&addr, sizeof(addr));
      if (err)
        {
	  printf("Could not connect to IP-Address: %s   Port: %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
	}
      else
	{
	  /* Connection has been accepted by Receiver. 
	     Now do some initialisations */
	  
	  /* Disable nagle algorithm to get better realtime responses */
	  int i=1;
	  setsockopt(m_nSocketID, IPPROTO_TCP, TCP_NODELAY,
		     (char*)&i, sizeof(i));
	  
	  /* Init device */
	  MySend(m_nSocketID, "*CLS\n"); /* clear status reporting */
	  MySend(m_nSocketID, "*RST\n"); /* reset Receiver */
	  
	  /* Reset RX_DATA_CHANGED bit in STATUS EXTENSION register to
	   * get SRQs, if someone changes the freq. */
	  MySend(m_nSocketID, "FREQ?\n");
	  ReadString(m_nSocketID, cBuffer, sizeof(cBuffer) - 1, true);
	  
	  /* Detect Receiver type */
	  MySend(m_nSocketID, "*idn?\n"); 
	  ReadString(m_nSocketID, cBuffer, sizeof(cBuffer) - 1, true);
	  
	  if ((strstr((char *)cBuffer,"EB200") != NULL) ||
	      (strstr((char *)cBuffer,"EB110") != NULL) ||
	      (strstr((char *)cBuffer,"EB130") != NULL) ||
	      (strstr((char *)cBuffer,"ESMB") != NULL) ||
	      (strstr((char *)cBuffer,"EM045") != NULL) ||
	      (strstr((char *)cBuffer,"EM050") != NULL) ||
	      (strstr((char *)cBuffer,"EM550") != NULL) ||
	      (strstr((char *)cBuffer,"ESMD") != NULL) ||
	      (strstr((char *)cBuffer,"DDF255") != NULL) ||
	      (strstr((char *)cBuffer,"DDF205") != NULL) ||
	      (strstr((char *)cBuffer,"EB500") != NULL))
            {
	      FreqStart = 1000000000;
	      FreqStop = 1100000000;
	      FreqStep = 500000;
	      BandWidth = 20000000;
            }
	  
	  else if (strstr((char *)cBuffer,"EM510") != NULL)
            {
	      FreqStart = 11800000;
	      FreqStop = 13600000;
	      FreqStep = 2500;
	      BandWidth = 2700;
	    }
	  else
            {
	      printf("unknown receiver type\n");
	      
	      /* exit program */
#ifdef LINUX
	      close(m_nSocketID);
#endif
            }
	  
          
	  /* FScan config */
	  sprintf(setbuf,"FREQ:PSC:STAR 800 MHz;STOP 3 GHz\n",FreqStart,FreqStop);
	  MySend(m_nSocketID, setbuf);
	  sprintf(setbuf,"FREQ:SPAN 20 MHz\n",FreqStep);
	  MySend(m_nSocketID, setbuf);
            
	  MySend(m_nSocketID, "DEM AM;DET PAV;GCON:MODE FIX\n");
	  
	  MySend(m_nSocketID, "INP:ATT:AUTO OFF\nINP:ATT 0\nOUTP:SQU:STAT OFF;THR 40 dbuV\n");
	  MySend(m_nSocketID, "PSC:COUN 1;STEP 2 MHz\n");
	  MySend(m_nSocketID, "MEAS:TIME 0.1 s\nCALC:IFPAN:AVER:TYPE MAX\n");
	  
	  /* Turn off offset measurement, turn on level measurement */
	  MySend(m_nSocketID, "FUNC:OFF 'FREQ:OFFS';ON 'VOLT:AC'\n");
	  
	  /* Trace config */
	  /* Store results only if level is over threshold */
	  MySend(m_nSocketID, "TRAC:FEED:CONT MTRACE,ALW;CONT ITRACE,ALW\n");
	  MySend(m_nSocketID, "TRAC:FEED:CONT IFPAN,ALW\n");
	  
	  /* Set notification limit to 80%.  We get
	     a printout (see ReadTraces()), if traces are overrunning */
	  MySend(m_nSocketID, "TRAC:LIM MTRACE,5 PCT;LIM ITRACE,5 PCT\n");
	  MySend(m_nSocketID, "TRAC:LIM IFPAN,5 PCT\n");
	  
	  /* Configure status reporting system */
	  /* Enable SRQ on STAT:OPER, STAT:TRAC, STAT:EXT events */
	  MySend(m_nSocketID, "*SRE #H87\n");
	  
	  /* Enable RX data changed events */
	  MySend(m_nSocketID, "STAT:EXT:ENAB 1\n");
	  
	  /* Enable MTRACE imit exceeded events */
	  MySend(m_nSocketID, "STAT:TRAC:ENAB #B10\n");
	  
	  /* Enable scan stop event */
	  MySend(m_nSocketID, "STAT:OPER:SWE:ENAB #B10\n");
	  MySend(m_nSocketID, "STAT:OPER:SWE:NTR #B10;PTR 0\n");
	  
	  /* Enable SWEEPING events in STAT:OPER register */
	  MySend(m_nSocketID, "STAT:OPER:ENAB #B1000\n");
	  
	  /* Switch to frequency scanning mode */
	  MySend(m_nSocketID,"FREQ:MODE PSC\n");
#if (!TRACE_ASCII)
	  MySend(m_nSocketID, "FORM:DATA PACK\n");
#if (BYTEORDER_SWAPPED)
	  MySend(m_nSocketID, "form:border swap\n");
#endif
#endif
	  MySend(m_nSocketID, "INIT\n");
          
	  /* Wait for SRQ. No other string should be received. */
	  while ((cloop == true) && ReadString(m_nSocketID, cBuffer, sizeof(cBuffer) -1, false))
            {
	      /* SRQ arrived. Now look for the SRQ event. */
	      do
                {
		  int nStb;
		  
		  bSrq = false;
		  
		  /* Get the serial poll byte (status byte) */
		  MySend(m_nSocketID, "&POL");
		  bSrq |= ReadString(m_nSocketID, cBuffer,
				     sizeof(cBuffer) -1, true);
		  
		  /* Convert Statusbyte to binary */
		  nStb = (cBuffer[1]-'0') * 100 + (cBuffer[2]-'0') * 10 + 
		    cBuffer[3] - '0';
		  /* printf("%d\n", nStb); */
		  
		  if (nStb & 1)
                    {
		      /* Someone changed the frequency (or any other
		       * RX parameter).  Now reset event and get the
		       * current frequency. */
		      
		      /* reset RX data changed event */
		      MySend(m_nSocketID, "stat:ext?\n");
		      bSrq |= ReadString(m_nSocketID, cBuffer,
					 sizeof(cBuffer) -1, true);
		      /* get current frequency */
		      MySend(m_nSocketID, "FREQ?\n");
		      bSrq |= ReadString(m_nSocketID, cBuffer,
					 sizeof(cBuffer) -1, true);
		      
		      /* printf("frequency: %s", cBuffer); */
                    }
		  if (nStb & 2)
                    {
		      printf("reading trace\n");
		      /* Trace limit exceeded. Read trace information. */
		      bSrq |= ReadTraces(m_nSocketID);
                    }
		  if (nStb & 4)
                    {
		      /* Error in error queue. Read error. */
		      MySend(m_nSocketID, "SYST:ERR?\n");
		      bSrq |= ReadString(m_nSocketID, cBuffer,
					 sizeof(cBuffer) -1, true);
		      /* printf("Error: %s", cBuffer); */
                    }
		  if (nStb & 128)
                    {
		      /* Scan stopped.
		       * Reset this event in status reporting system. */
		      MySend(m_nSocketID, "STAT:OPER?;:STAT:OPER:SWE?\n");
		      bSrq |= ReadString(m_nSocketID, cBuffer,
					 sizeof(cBuffer) -1, true);
		      
		      /* Read the rest of the trace information. */
		      bSrq |= ReadTraces(m_nSocketID);
		      
		      /* printf("Scan stopped.\n"); */
		      
		      /* exit program */
		      close(m_nSocketID);
                    }
                } while ((cloop == true) && bSrq); /* loop til no SRQ is received */
            }   /* loop forever */
	  printf("Error: no SRQ message received: <%s>\n", cBuffer);
	  close(m_nSocketID);
	  m_nSocketID = -1;
        }
    }

    return 0;
}


int scmp (const void *a, const void *b) {
  _spectralpoint *aa, *bb;
  aa = (_spectralpoint*)a;
  bb = (_spectralpoint*)b;
  return ( aa->frequency - bb->frequency);
}

int acmp (const void *a, const void *b) {
  return (*(float*)a - *(float*)b);
}

void make_plot(void) {

  float *freq=NULL, *amp=NULL, *mamp=NULL, median, minamp, maxamp;
  int i;
  FILE *fp = NULL;

  n_spectralpoints++;

  freq = malloc(n_spectralpoints * sizeof(float));
  amp = malloc(n_spectralpoints * sizeof(float));
  mamp = malloc(n_spectralpoints * sizeof(float));

  // Sort the input.
  qsort(spectralpoints, n_spectralpoints, sizeof(_spectralpoint), scmp);

  for (i = 0; i < n_spectralpoints; i++) {
    freq[i] = (float)spectralpoints[i].frequency / 1e6;
    if (spectralpoints[i].nlevels > 0) {
      amp[i] = (float)spectralpoints[i].levelsum / (float)spectralpoints[i].nlevels;
    } else {
      amp[i] = 0.0;
    }
    mamp[i] = amp[i];
    /* printf("freq %.3f amp %.3f\n", freq[i], amp[i]); */
  }

  // Take the median of the amplitude array.
  qsort(mamp, n_spectralpoints, sizeof(float), acmp);
  median = mamp[n_spectralpoints / 2];
  for (i = 1; i < n_spectralpoints; i++) {
    amp[i] -= median;
    if (i == 0) {
      minamp = maxamp = amp[i];
    } else {
      minamp = (amp[i] < minamp) ? amp[i] : minamp;
      maxamp = (amp[i] > maxamp) ? amp[i] : maxamp;
    }
  }

  /* Make a plot. */
  /* cpgopen("11/xs"); */
  /* cpgswin(1e3, 3e3, minamp, maxamp); */
  /* cpgbox("BCNTS", 0, 0, "BCNTS", 0, 0); */
  /* cpgline(n_spectralpoints, freq, amp);  */
  /* cpgclos(); */

  fp = fopen("rfi_spectrum.txt", "w");
  for (i = 1; i < n_spectralpoints; i++) {
    fprintf(fp, "%.4f  %.4f\n", freq[i], amp[i]);
  }
  fclose(fp);

  exit(0);
}
